package com.zenithmind.library.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.library.mapper.BookMapper;
import com.zenithmind.library.mapper.PublisherMapper;
import com.zenithmind.library.pojo.domain.Publisher;
import com.zenithmind.library.pojo.dto.PublisherCreateDTO;
import com.zenithmind.library.pojo.dto.PublisherUpdateDTO;
import com.zenithmind.library.pojo.query.PublisherQuery;
import com.zenithmind.library.pojo.vo.PublisherVO;
import com.zenithmind.library.service.PublisherService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 出版社服务实现类
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PublisherServiceImpl extends ServiceImpl<PublisherMapper, Publisher> implements PublisherService {

    private final PublisherMapper publisherMapper;
    private final BookMapper bookMapper;

    @Override
    @Cacheable(value = "publishers", key = "'page:' + #query.hashCode()")
    public PageResult<PublisherVO> getPublisherPage(PublisherQuery query) {
        log.info("分页查询出版社，查询条件：{}", query);

        Page<PublisherVO> page = query.toPage();
        IPage<PublisherVO> result = publisherMapper.selectPublisherPage(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "publishers", key = "'detail:' + #id")
    public PublisherVO getPublisherDetail(String id) {
        log.info("查询出版社详情，ID：{}", id);
        
        Publisher publisher = getById(id);
        if (publisher == null) {
            throw new RuntimeException("出版社不存在");
        }
        
        return convertToVO(publisher);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<PublisherVO> createPublisher(PublisherCreateDTO createDTO) {
        log.info("创建出版社，数据：{}", createDTO);
        
        // 检查出版社编码是否已存在
        if (StringUtils.hasText(createDTO.getCode()) && 
            existsByCode(createDTO.getCode(), null)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社编码已存在", null);
        }
        
        // 检查出版社名称是否已存在
        if (existsByName(createDTO.getName(), null)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社名称已存在", null);
        }
        
        // 转换为实体对象
        Publisher publisher = new Publisher();
        BeanUtils.copyProperties(createDTO, publisher);
        
        publisher.setStatus(1); // 默认启用
        publisher.setBookCount(0); // 初始图书数量为0
        publisher.setCreateTime(LocalDateTime.now());
        publisher.setUpdateTime(LocalDateTime.now());
        
        // 保存出版社
        boolean saved = save(publisher);
        if (!saved) {
            return Result.fail(ResultCode.FAIL.getCode(), "创建出版社失败", null);
        }
        
        // 返回创建的出版社信息
        PublisherVO publisherVO = convertToVO(publisher);
        return Result.success(publisherVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<PublisherVO> updatePublisher(String id, PublisherUpdateDTO updateDTO) {
        log.info("更新出版社，ID：{}，数据：{}", id, updateDTO);
        
        // 检查出版社是否存在
        Publisher existingPublisher = getById(id);
        if (existingPublisher == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社不存在", null);
        }
        
        // 检查出版社编码是否已被其他出版社使用
        if (StringUtils.hasText(updateDTO.getCode()) && 
            existsByCode(updateDTO.getCode(), id)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社编码已被其他出版社使用", null);
        }
        
        // 检查出版社名称是否已被其他出版社使用
        if (StringUtils.hasText(updateDTO.getName()) && 
            existsByName(updateDTO.getName(), id)) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "出版社名称已被其他出版社使用", null);
        }
        
        // 更新出版社信息
        Publisher publisher = new Publisher();
        BeanUtils.copyProperties(updateDTO, publisher);
        publisher.setId(id);
        publisher.setUpdateTime(LocalDateTime.now());
        
        boolean updated = updateById(publisher);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社失败", null);
        }
        
        // 返回更新后的出版社信息
        Publisher updatedPublisher = getById(id);
        PublisherVO publisherVO = convertToVO(updatedPublisher);
        return Result.success(publisherVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> deletePublisher(String id) {
        log.info("删除出版社，ID：{}", id);
        
        // 检查出版社是否存在
        Publisher publisher = getById(id);
        if (publisher == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社不存在", null);
        }
        
        // 检查是否有图书关联
        Long bookCount = bookMapper.countBooksByPublisher(id);
        if (bookCount != null && bookCount > 0) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "该出版社下还有图书，无法删除", null);
        }
        
        // 删除出版社
        boolean deleted = removeById(id);
        if (!deleted) {
            return Result.fail(ResultCode.FAIL.getCode(), "删除出版社失败", null);
        }
        
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> batchDeletePublishers(List<String> ids) {
        log.info("批量删除出版社，IDs：{}", ids);
        
        // 检查每个出版社是否可以删除
        for (String id : ids) {
            Publisher publisher = getById(id);
            if (publisher == null) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "出版社不存在：" + id, null);
            }
            
            if (publisher.getBookCount() != null && publisher.getBookCount() > 0) {
                return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "出版社《" + publisher.getName() + "》下还有图书，无法删除", null);
            }
        }
        
        // 批量删除
        boolean deleted = removeByIds(ids);
        if (!deleted) {
            return Result.fail(ResultCode.FAIL.getCode(), "批量删除出版社失败", null);
        }
        
        return Result.success();
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> enablePublisher(String id) {
        log.info("启用出版社，ID：{}", id);
        return updatePublisherStatus(id, 1);
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> disablePublisher(String id) {
        log.info("禁用出版社，ID：{}", id);
        return updatePublisherStatus(id, 0);
    }

    @Override
    @Cacheable(value = "publishers", key = "'name:' + #name")
    public List<PublisherVO> getPublishersByName(String name) {
        log.info("根据名称查询出版社，名称：{}", name);
        return publisherMapper.selectByName(name);
    }

    @Override
    @Cacheable(value = "publishers", key = "'code:' + #code")
    public PublisherVO getPublisherByCode(String code) {
        log.info("根据编码查询出版社，编码：{}", code);
        return publisherMapper.selectByCode(code);
    }

    @Override
    public List<PublisherVO> searchPublishers(String keyword, Integer limit) {
        log.info("搜索出版社，关键词：{}，限制数量：{}", keyword, limit);
        return publisherMapper.searchPublishers(keyword, limit);
    }

    @Override
    @Cacheable(value = "publishers", key = "'hot:' + #limit")
    public List<PublisherVO> getHotPublishers(Integer limit) {
        log.info("获取热门出版社，限制数量：{}", limit);
        return publisherMapper.selectHotPublishers(limit);
    }

    @Override
    @Cacheable(value = "publishers", key = "'country:' + #country")
    public List<PublisherVO> getPublishersByCountry(String country) {
        log.info("根据国家查询出版社，国家：{}", country);
        return publisherMapper.selectByCountry(country);
    }

    @Override
    @Cacheable(value = "publishers", key = "'city:' + #city")
    public List<PublisherVO> getPublishersByCity(String city) {
        log.info("根据城市查询出版社，城市：{}", city);
        return publisherMapper.selectByCity(city);
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> updatePublisherBookCount(String publisherId) {
        log.info("更新出版社图书数量，出版社ID：{}", publisherId);
        
        // TODO: 实现图书数量统计逻辑
        // Integer bookCount = bookMapper.countBooksByPublisher(publisherId);
        // publisherMapper.updateBookCount(publisherId, bookCount);
        
        return Result.success();
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> incrementPublisherBookCount(String publisherId) {
        log.info("增加出版社图书数量，出版社ID：{}", publisherId);
        
        int updated = publisherMapper.incrementBookCount(publisherId);
        if (updated == 0) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社图书数量失败", null);
        }
        
        return Result.success();
    }

    @Override
    @CacheEvict(value = "publishers", allEntries = true)
    public Result<Void> decrementPublisherBookCount(String publisherId) {
        log.info("减少出版社图书数量，出版社ID：{}", publisherId);
        
        int updated = publisherMapper.decrementBookCount(publisherId);
        if (updated == 0) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社图书数量失败", null);
        }
        
        return Result.success();
    }

    @Override
    public boolean existsByCode(String code, String excludeId) {
        return publisherMapper.existsByCode(code, excludeId);
    }

    @Override
    public boolean existsByName(String name, String excludeId) {
        return publisherMapper.existsByName(name, excludeId);
    }

    @Override
    public Result<String> importPublishers(List<PublisherCreateDTO> publishers) {
        log.info("导入出版社数据，数量：{}", publishers.size());
        
        // TODO: 实现批量导入逻辑
        return Result.success("导入成功");
    }

    @Override
    public Result<String> exportPublishers(PublisherQuery query) {
        log.info("导出出版社数据，查询条件：{}", query);
        
        // TODO: 实现数据导出逻辑
        return Result.success("/exports/publishers_" + System.currentTimeMillis() + ".xlsx");
    }

    /**
     * 更新出版社状态
     */
    private Result<Void> updatePublisherStatus(String id, Integer status) {
        Publisher publisher = new Publisher();
        publisher.setId(id);
        publisher.setStatus(status);
        publisher.setUpdateTime(LocalDateTime.now());
        
        boolean updated = updateById(publisher);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新出版社状态失败", null);
        }
        
        return Result.success();
    }

    /**
     * 转换为VO对象
     */
    private PublisherVO convertToVO(Publisher publisher) {
        PublisherVO publisherVO = new PublisherVO();
        BeanUtils.copyProperties(publisher, publisherVO);
        return publisherVO;
    }
}
